//---------------------------------------------------------------------------------
// Copyright (c) 2008 VoiceLynx Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

#include "VLDataStream.h"


void OutDataStream::insertObject(const void *object,int length)
{
  //TODO: Make the perf here not awful
  byte*toInsert=(byte*)object;
  for(int i=0;i<length;++i)
    mData->push_back(toInsert[i]);
}

OutDataStream::OutDataStream()
: mData(new VLByteArray())
{
}

OutDataStream::~OutDataStream()
{
}

void OutDataStream::writeData(const std::string &name, int data)
{
  byte t=intType;
  insertObject(&t,sizeof(byte));//type
  insertObject(&data,sizeof(int));//data
}

void OutDataStream::writeData( const std::string &name, unsigned int data )
{
  byte t=unsignedIntType;
  insertObject(&t,sizeof(byte));//type
  insertObject(&data,sizeof(unsigned int));//data
}

void OutDataStream::writeData( const std::string &name, bool data )
{
  byte t=boolType;
  insertObject(&t,sizeof(byte));//type
  insertObject(&data,sizeof(bool));//data
}

void OutDataStream::writeData(const std::string &name, std::string &data)
{
  byte t=stringType;
  insertObject(&t,sizeof(byte));//type
  int size=int(data.size());
  insertObject(&size,sizeof(int));//size
  for(size_t i = 0; i < data.size(); ++i)
    mData->push_back(data.at(i));
}

void OutDataStream::writeData(const std::string &name, float &data)
{
  byte t=floatType;
  insertObject(&t, sizeof(byte));
  insertObject(&data,sizeof(float));
}

void OutDataStream::writeData(const std::string &name, VLByteArray &data)
{
  byte t=byteArrayType;
  size_t size=data.size();
  insertObject(&t, sizeof(byte));
  insertObject(&size, sizeof(size_t));
  insertObject(&data[0], size);
}

VLByteArrayPtr OutDataStream::takeData()
{
  VLByteArrayPtr returnVal = mData;

  mData.reset(new VLByteArray());

  return returnVal;
}

InDataStream::InDataStream(std::auto_ptr<std::vector<byte> > data)
: mData(data),
mDataPtr(0)
{

}

InDataStream::~InDataStream()
{

}

void InDataStream::getObject(void *object, int length, bool advanceReadPointer)
{
  assert(mDataPtr + length <= (int) mData->size());

  memcpy(object, &((*mData)[mDataPtr]), length);
  if (advanceReadPointer)
  {
    mDataPtr += length;
  }
}

void InDataStream::readData(const std::string &name, int *data)
{
  byte t;
  getObject(&t, sizeof(byte));
  assert(t == intType);
  getObject(data, sizeof(int));
}



void InDataStream::readData( const std::string &name, unsigned int *data )
{
  byte t;
  getObject(&t, sizeof(byte));
  assert(t == unsignedIntType);
  getObject(data, sizeof(unsigned int));
}

void InDataStream::readData( const std::string &name, bool *data )
{
  byte t;
  getObject(&t, sizeof(byte));
  assert(t == boolType);
  getObject(data, sizeof(bool));
}

void InDataStream::readData(const std::string &name, std::string *data)
{
  byte t;
  getObject(&t, sizeof(byte));
  assert(t == stringType);

  int size = 0;
  getObject(&size, sizeof(int));

  if (size != 0)
  {
    data->assign((char *) &((*mData)[mDataPtr]), size);
    mDataPtr += (int) data->size(); //we read x chars plus a null terminator
  }
}

void InDataStream::readData(const std::string &name, float *data)
{
  byte t;
  getObject(&t, sizeof(byte));
  assert(t == floatType);
  getObject(data, sizeof(float));
}

void InDataStream::readData(const std::string &name, VLByteArray &data)
{
  byte t;
  size_t size;
  getObject(&t, sizeof(byte));
  assert(t == byteArrayType);
  getObject(&size, sizeof(size_t));
  data.resize(size);

  if (size > 0)
  {
    getObject(&data[0], size);
  }
}

void InDataStream::reset()
{
  mDataPtr = 0;
}

bool InDataStream::isEmpty()
{
  return (mDataPtr >= (int) mData->size());
}